
function CanvasGrid(){
	this.options = {}
}

/**
 * Main CanvasGrid
 */
CanvasGrid.run = function( options ){
		
	this.options = options;
	this.array = new Array(this.options.numItems);
	this.benchmarks = {};
	this.canvas = null;
	this.drawingCtx = null;
	
	// Validate options
	if ( !this.options || this.options == undefined ){
		throw new Error('No options for CanvasGrid');
	}
	if ( !this.options.node || !(this.options.node instanceof HTMLDivElement)){
		throw new Error('No root node for CanvasGrid');
	}
	
	// Populate the array
	Timer.start();
	for ( var i = 0;  i < this.options.numItems;  i++ ){
		this.array[i] = Math.floor(Math.random() * this.options.maxValue );
	}
	Timer.bench();this.benchmarks.arrayCreate = Timer.result;
	var h = new Heap(this.array);
	h.heapify();h.sort();
	
	// Prepare the canvas element
	this.canvas = document.createElement('canvas');
	this.drawingCtx = this.canvas.getContext('2d');
	this.canvas.width = (window.innerWidth - 20);
	this.canvas.height = (window.innerWidth - 10);
	this.canvas.id = 'tree';
	this.canvas.style.border = '1px solid #000';
	this.options.node.appendChild(this.canvas);	
	
	// Render the tree
	CanvasGrid.drawGrid();
}

CanvasGrid.drawGrid = function(){
	var top = 0;
	var left = 0;
	var step = 10;
	var xSteps = Math.floor(this.canvas.width / 10);
	var ySteps = Math.floor(this.canvas.height / 10);
	this.drawingCtx.beginPath();
	for ( var i=0; i < xSteps; i++ ){
		this.drawingCtx.moveTo((10 * i), 0);
		this.drawingCtx.strokeLine( (10 * i), this.canvas.height);
	}
	this.drawingCtx.closePath();
}

CanvasGrid.clear = function(){
	this.drawingCtx.clearRect(0,0,this.canvas.width, this.canvas.height);
}

CanvasGrid.drawTree = function(){
	// Calculate starting coordinates
	var top = 50;
	var rootNode = CanvasGrid.heapToTree(0);
	this.drawingCtx.beginPath();
	CanvasGrid.drawNode(rootNode, top, 0, CanvasGrid.canvas.width);
	this.drawingCtx.closePath();
}

CanvasGrid.drawNode = function( node, top, canvasLeft, canvasRight ){
	if ( ! node ) return;
	var coords = {},
		midPoint = canvasLeft + ((canvasRight - canvasLeft) >> 1),
		left = midPoint - (CanvasGrid.options.boxWidth >> 1);

	// Draw the node
	CanvasGrid.drawingCtx.font = CanvasGrid.options.font;
	CanvasGrid.drawingCtx.strokeRect( left, top, CanvasGrid.options.boxHeight, CanvasGrid.options.boxWidth);
	// Draw the value
	CanvasGrid.drawingCtx.fillText(node.getValue(), left + ((midPoint - left) >> 1), top + 35);
	
	// Calculate the left/right location
	top = top + (CanvasGrid.options.boxHeight * 1.5);
	
	// Draw the left child
	CanvasGrid.drawNode(node.getLeft(), top, canvasLeft, midPoint);
	// Draw the Right child
	CanvasGrid.drawNode(node.getRight(), top, midPoint, canvasRight);
}

CanvasGrid.heapToTree = function( idx ){
	var value = CanvasGrid.array[idx];
	var max = CanvasGrid.array.length;
	
	// If we're outside the array, return
	if ( value == undefined ) return null;
	
	function getLeftChild( index ){
		// Use bit shifting for mutliplication
		var child = ( index << 1 ) + 1;
		return ( child < max ) ? child : false;		
	}
	
	function getRightChild( index ){
		// Use bit shifting for mutliplication
		var child = ( index << 1 ) + 2;
		return ( child < max ) ? child : false;
	}
	
	var objNode = new TreeNode( value );
	var leftIdx = getLeftChild( idx );
	var rightIdx = getRightChild( idx );
	if ( leftIdx != false ){
		objNode.setLeft(CanvasGrid.heapToTree(leftIdx));
	}
	if ( rightIdx != false ){
		objNode.setRight(CanvasGrid.heapToTree(rightIdx));
	}
	return objNode;
}